# -*- coding: utf-8 -*-
import time
import inspect
import subprocess
import threading
import ctypes
import datetime
import traceback
import yaml
import os
from filelock import FileLock
from src.lib.dmlib import DM
from src.util.util import GetLog


class Dota2(threading.Thread):

    def __init__(self, thread_id, name, index, public_data,ignore_block=False):
        threading.Thread.__init__(self)
        self.threadID = thread_id
        self.name = name
        self.index = index
        self.publicData = public_data
        self.hwnd = 0

        self.log = GetLog(str(self.threadID) + self.name  +".log")
        self.log.info("日志初始化完成")

        dm_obj = DM(log=self.log, public_data=public_data, ignore_wait=ignore_block)
        self.dm = dm_obj
        self.log.info("dm初始化完成")
        self.flag=""
        self.subThread=""
        self.cost_time_tag=0.0



    def cost_time_debug(self, tag,init=False):
        now = time.time()
        if init:
            self.cost_time_tag=now
            self.log.info("cost_time_debug init")
        else:
            self.log.info("cost_time_debug %s : %s" % (tag,now - self.cost_time_tag))
            self.cost_time_tag=now

    def SetSubThread(self,subThread):
        self.subThread=subThread

    def Process(self):
        return 1
    def LogTraceback(self):
        self.log.error(traceback.format_exc())

    @staticmethod
    def makeDir(path):
        dir_path = os.path.dirname(path)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

    def Stop(self):
        self.dm.UnBindWindow()
        self.log.info("开始设置flag 为退出")
        self.log.info(inspect.stack())
        self.flag = "EXIT"
        thread_id = ctypes.c_long(self.ident)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
        self.log.info(res)
        if res == 0:
            pass
        elif res != 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, None)
            raise SystemError("EXIT")

    def CustomPause(self):
        self.log.info(self.flag)
        self.flag = "PAUSE"
        self.log.info(self.flag)
        self.dm.isPause=True
        # thread_id = ctypes.c_long(self.ident)
        # res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
        # self.log.info(res)
        # if res == 0:
        #     pass
        # elif res != 1:
        #     ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, None)
        #     raise SystemError("PAUSE")

        self.log.info(self.flag)
    def CustomGoOn(self):
        self.log.info(self.flag)
        self.flag = "RUNNING"
        self.log.info(self.flag)
        self.dm.isPause=False
        self.log.info(self.flag)
    # def CustomBreak(self):
    #     thread_id = ctypes.c_long(self.ident)
    #     res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
    #     self.log.info(res)
    #     if res == 0:
    #         pass
    #     elif res != 1:
    #         ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, None)
    #         raise SystemError("break")

    def breakGame(self):
        if self.subThread=="":
            return
        self.subThread.CustomBreak()

    def DotaAttack(self, x1, y1, x2, y2):
        if x1 != 0 and y1 != 0:
            self.dm.LeftClick(x1, y1, 1)
            time.sleep(0.674)
        self.dm.MoveTo(x2, y2)
        self.dm.KeyPressChar("a")
    def CheckPersonPosition(self, sx, sy, similarity, count, step_time, x1, y1, x2, y2):
        if sx!=0 and sy!=0:
            self.dm.LeftClick(sx, sy, 1)
        is_get = self.dm.SearchPngClick(x1, y1, x2, y2, "存档\人物血条.bmp|存档\人物血条2.bmp", similarity, count,
                                        step_time, 0, 0, 0)
        return is_get
    def CheckPersonPositionSuper(self, sx, sy, similarity, count, step_time, x1, y1, x2, y2):
        if sx!=0 and sy!=0:
            self.dm.dm.LeftClick(sx, sy, 1)
        is_get = self.dm.SearchPngClick(x1, y1, x2, y2, "存档\人物血条.bmp|存档\人物血条2.bmp", similarity, count,
                                        step_time, 0, 0, 0)
        return is_get

    def GetDatetime(self, timestamp):
        date_time_obj = datetime.datetime.fromtimestamp(timestamp)
        return date_time_obj
    # 移动后攻击
    def DotaCheckMoveAttack(self, x1, y1, x2, y2, rx=100, ry=150, step=0.5, n=10):
        if x1 != 0 and y1 != 0:
            self.dm.LeftClick(x1, y1, 1)
        for i in range(n):
            is_get = self.CheckPersonPosition(0, 0, 0.9, 1, 0.5, x2 - rx, y2 - ry, x2 + rx, y2+ry)
            if is_get == 1:
                cx,xy=0,0
                if x2 +100>1280:
                    cx=x2-100
                else:
                    cx = x2+100
                self.dm.MoveTo(cx,y2)
                self.dm.KeyPressChar("a",step=0.05)
                self.dm.KeyPressChar("e", step=0.05)
                return 1
            self.dm.RightClick(x2, y2, 1)
            time.sleep(step)
        return 0

    # 攻击中移动 适合守家
    def DotaCheckAttackMove(self, x1, y1, x2, y2, rx=100, ry=100, step=0.5, n=10):
        if x1 != 0 and y1 != 0:
            self.dm.LeftClick(x1, y1, 1)
        time.sleep(0.674)
        for i in range(n):
            time.sleep(step)
            is_get = self.CheckPersonPosition(0, 0, 0.9, 1, 1, x2 - rx, y2 - ry, x2 + rx, y2)
            if is_get == 1:

                return 1
            self.dm.MoveTo(x2, y2)
            self.dm.KeyPressChar("a")

        return 0

    def DotaMove(self, x1, y1, x2, y2):
        if x1 != 0 and y1 != 0:
            self.dm.LeftClick(x1, y1, 1)
        time.sleep(0.674)
        self.dm.RightClick(x2, y2, 1)

    def DotaBlink(self, x1, y1, x2, y2,n=1):
        if x1 != 0 and y1 != 0:
            self.dm.LeftClick(x1, y1, 1)
            time.sleep(0.3)
        self.dm.MoveTo(x2,y2)
        # self.dm.LeftClick(x2, y2, 1)
        self.dm.KeyPressChar("d",num=n)
        self.dm.KeyPressChar("a")

    # 定制函数不等待 非特殊情况不使用
    def DotaBlinkSuper(self, x2, y2,n=1):
        self.dm.dm.MoveTo(x2, y2)
        time.sleep(0.08)
        self.dm.dm.LeftClick()
        for i in range(n):
            self.dm.dm.KeyPressChar("d")
            time.sleep(0.25)
            self.dm.dm.MoveTo(x2, y2)
        self.dm.dm.KeyPressChar("a")


    # 等待暂停结束
    # 1 暂停中
    # 0 不在暂停中
    # 2 暂停恢复
    def WaitePauseEnd(self):
        self.log.info("开始查询比赛暂停")
        res = self.dm.SearchPngClick(585, 254, 696, 276, "dota2\比赛暂停.bmp", 0.9, 1, 0, 0, 0, 0)
        if res==1:
            res = self.dm.SearchPngClick(585, 254, 696, 276, "dota2\比赛暂停.bmp", 0.9, 3, 0.5, 0, 0, 0, is_wait=1)
            if res==1:
                return 1
        else:
            return  0
        return 2

    def WaitDota2Load(self):
        dota2_hwnd = self.hwnd
        self.dm.SetWindowState(dota2_hwnd, 1)
        x,y=self.publicData["系统"]["窗口位置"].split(",")
        self.dm.MoveWindow(dota2_hwnd, x, y)
        self.log.info("等待dota2进入主界面")
        for i in range(30):
            res=self.dm.GetClientRect(dota2_hwnd)
            if res[4]==0:
                time.sleep(10)
                continue
            self.LowProbabilityAnomalyStart(1,res[0],res[1])
            # is_get = self.dm.SearchPngClick(res[0], res[1], res[2], res[3], "f4.bmp|f4_2.bmp|f4_3.bmp|dota2\游廊.bmp|dota2\训练.bmp|dota2\游廊_1.bmp|dota2\英雄.bmp|dota2\兵器库.bmp",
            #                                 0.8, 10, 1, 0, 0, 0)
            is_get = self.dm.SearchPngClick(810, 425, 1245, 655, "dota2\离开比赛.bmp|dota2\离开比赛2.bmp", 0.8, 1, 1, 1, 10, 10)
            is_get = self.dm.SearchPngClick(res[0]+30, res[1]+5, res[0]+100, res[1]+33, "dota2\设置.bmp|dota2\设置2.bmp|dota2\设置3.bmp|dota2\设置右.bmp", 0.9, 5, 1, 0, 0, 0)
            is_get2 = self.dm.SearchPngClick(res[0] + 1080, res[1] + 676, res[0] +1183, res[1] + 700, "dota2\开始dota.bmp|dota2\开始dota2.bmp", 0.9,
                                            5, 1, 0, 0, 0)
            if is_get == 1 or is_get2==1:
                self.log.info("dota2已经完成加载")
                self.dm.MoveWindow(dota2_hwnd, x, y)
                return 1
            is_get = self.dm.SearchPngClick(462, 267, 816, 452,
                                            "dota2\需更新.bmp|dota2\需更新2.bmp|dota2\游戏无网络.bmp", 0.8, 1, 0.1, 1,
                                            128, 108)
            if is_get == 1:
                self.dm.DebugScreen(r"dota2需更新")
                self.publicData["是否需要重启"] = True
                time.sleep(30)

    def StartDota2(self):
        app_path = self.publicData["系统"]["steam路径"] + r" steam://rungameid/570"
        if self.publicData["系统"]["启动模式"]=="沙盒":
            app_path ="%s  /box:%s %s"%(self.publicData["系统"]["沙盒路径"],self.publicData["系统"]["沙盒名称"],app_path)
        for i in range(30):
            dota2_hwnd = self.dm.FindWindow(self.publicData["dota2_class_name"], self.publicData["dota2_tittle"])
            if dota2_hwnd == 0 and i in [0, 10, 20]:
                subprocess.Popen(app_path)
                # subprocess.run(app_path) # 会阻塞
            elif dota2_hwnd > 0:
                self.hwnd = dota2_hwnd
                self.log.info("dota2句柄 %s" % dota2_hwnd)
                return 1
            time.sleep(10)
        return 0


    def ExitGame(self):
        if self.publicData["系统"]["多少局重启一次dota2"] != 0 :
            dota2_hwnd = self.dm.FindWindow(self.publicData["dota2_class_name"], self.publicData["dota2_tittle"])
            if self.index % self.publicData["系统"]["多少局重启一次dota2"] == 0 and dota2_hwnd != 0:
                return 0
        for i in range(5):
            self.dm.LeftClick(16, 14, 1)
            time.sleep(2)
            self.log.info("开始查找断开连接")
            is_get = self.dm.SearchPngClick(1010, 625, 1245, 655, "dota2\断开连接.bmp|dota2\断开连接2.bmp", 0.8, 5, 1,
                                            1, 10, 10, is_wait=1)


            if is_get == 1:
                break
            is_get = self.dm.SearchPngClick(462, 267, 816, 452, "dota2\需更新.bmp|dota2\需更新2.bmp", 0.8, 1, 0, 1,
                                            128, 108)
            if is_get == 1:
                return -1
        time.sleep(0.57)
        is_found=0
        for i in range(10):
            is_get = self.dm.SearchPngClick(471, 180, 906, 724, "存档\评价图.bmp|存档\评价图1.bmp|存档\评价图2.bmp",
                                            0.8, 1, 0, 0, 0, 0)
            if is_get == 1:
                self.log.info("游戏评价")
                self.dm.LeftClick(609, 499, 1)
            is_get=self.dm.SearchPngClick(810, 425, 1245, 655, "dota2\离开比赛.bmp|dota2\离开比赛2.bmp", 0.8, 1, 0.6, 1, 10, 10)
            if is_get==1:
                is_found=1
            if is_found==1 and is_get==0:
                break



    # 重新进入房间列表页面
    def retryInRoomList(self):
        self.dm.SendStringIme2(self.hwnd, "", 200)
        for i in range(10):
            self.dm.LeftClick(753, 19, 1)
            is_get = self.dm.SearchPngClick(345, 45, 500, 70, "dota2\房间列表0.bmp|dota2\房间列表1.bmp", 0.8, 100, 0.3,
                                            0, 0, 0)

            if is_get == 1 :
                self.dm.LeftClick(457, 61, 1)
                is_get2 = self.dm.SearchPngClick(515, 538, 705, 572, "dota2\寻找私人房间.bmp|dota2\寻找私人房间2.bmp",
                                                 0.8, 30, 0.3,0, 0, 0)
                if is_get2 ==1:
                    break


        time.sleep(0.768)

        is_get = self.dm.SearchPngClick(176, 544, 229, 567, r"dota2\309.bmp", 0.8, 1, 0.5, 1, 0, 0)
        if is_get == 0:
            while True:
                self.dm.LeftClick(360, 600, 1)
                is_get = self.dm.SearchPngClick(176, 544, 398, 567, "dota2\搜索房间.bmp", 0.8, 3, 0.5, 1, 0, 0)
                self.log.info(is_get)
                if is_get == 0:
                    self.dm.LeftClick(360, 560, 1)
                    self.log.info("删除地图名")
                    x = 6
                    while x > 0:
                        self.dm.KeyPress(8)
                        x -= 1
                self.dm.LeftClick(360, 560, 1)
                self.log.info("输入3.09")
                time.sleep(1)
                # self.dm.KeyPressStr("3.09", 20)
                res = self.dm.KeyPressStr("3.09", 20)
                time.sleep(0.52)
                # res = self.dm.KeyPressChars("3.09")
                is_get = self.dm.SearchPngClick(176, 544, 229, 567, r"dota2\309.bmp", 0.8, 3, 0.5, 0, 0, 0)
                if is_get == 1:
                    break
        # 房间名字过滤
        time.sleep(0.768)
        self.dm.LeftClick(600, 560, 1)
        time.sleep(1)
        self.dm.LeftClick(500, 360, 1)


        res = self.dm.KeyPressStr(self.publicData["基础配置"]["房间密码"], 60)
        time.sleep(1)
        is_get = self.dm.SearchPngClick(450, 350, 694, 378, "dota2\密码.bmp", 0.8, 3, 0.5, 0, 0, 0)
        self.log.info(is_get)
        if is_get == 0:
            self.dm.LeftClick(600, 560, 1)
            # res = self.dm.KeyPressChar("1")
            res = self.dm.KeyPressStr( self.publicData["基础配置"]["房间密码"], 60)
            # res = self.dm.KeyPressChars(self.publicData["基础配置"]["房间密码"])
        path = "dota2\创建房间好的.bmp|dota2\创建房间好的2.bmp"

        self.dm.SearchPngClick(620, 390, 725, 415, path, 0.9, 10, 0.3, 1, 5, 5, is_wait=1)

    @staticmethod
    # 0-5
    def GetValueIndex(objList, value):
        # 需要放到工具类里 todo
        for i in range(len(objList)):
            if objList[i] == value:
                return i
        return -1

    @staticmethod
    def LoadCustomConf(path, tag="",exclude=""):
        with open(path, "r", encoding="utf-8") as f:
            res= yaml.safe_load(f.read())

            if tag!="":
                tmp = []
                for line in res:
                    if line.strip()in exclude:
                        continue

                    tmp.append(os.path.join(tag, line.strip()))
                return tmp
            else:
                return res
    def get_main_stage(self):
        return self.publicData["系统"]["主要阶段"]



    def LowProbabilityAnomaly(self,n):
        x=int(time.time()*10000)
        if x/n==1:
            is_get = self.dm.SearchPngClick(600, 190, 710, 220, "dota2\组队邀请.bmp", 0.8, 1, 0, 1, 120, 250)
        return 0

    def LowProbabilityAnomalyStart(self,n,x=0,y=0):
        t=int(time.time()*10000)
        self.log.info("低频率数据%s ， %s "%(t,n))
        if t%n==0:
            is_get = self.dm.SearchPngClick(600+x, 190+y, 710+x, 220+y, "dota2\组队邀请.bmp", 0.8, 1, 0, 1, 120, 250)
            is_get = self.dm.SearchPngClick(475+x, 523+y, 820+x, 574+y, "dota2\礼物接受.bmp|dota2\礼物接受2.bmp", 0.8, 1, 0, 1, 5, 5)
            is_get = self.dm.SearchPngClick(462+x, 267+y, 816+x, 452+y, "dota2\需更新.bmp|dota2\需更新2.bmp", 0.8, 1, 0, 1,
                                            128, 108)
            is_get = self.dm.SearchPngClick(200+x, 100+y, 820+x, 574+y, "dota2\玩家行为总结.bmp", 0.8, 1, 0, 1, 0,0)
            if is_get==1:
                self.dm.LeftClick(620+x,548+y,1)


        return 0

    def BindDOTA2Game(self):
        n = 20
        self.log.info("开始绑定dota2 获取锁")
        with FileLock(self.publicData["系统"]["文件锁路径"]):
            self.log.info("获取锁成功")
            while n > 0:
                n -= 1
                self.dm.SetWindowState(self.hwnd, 1)
                time.sleep(0.1)
                res, err_msg = self.dm.BindWindowEx(self.hwnd, self.publicData["系统"]["绑定模式"])
                self.log.info("游戏进程绑定窗口结果 %s 错误码 %s" % (res, err_msg))
                if res == 1:
                    time.sleep(1)
                    self.dm.SetWindowState(self.hwnd, 1)
                    self.log.info("绑定完成释放锁")
                    return 1
        return 0